home *** CD-ROM | disk | FTP | other *** search
- #!/usr/local/bin/perl
- # makehosts - Make a /etc/hosts file by searching DNS records
- #
- # $Id: dnsfind.shar,v 8.2 1996/10/25 17:07:55 vixie Exp $
- #
- # SYNOPSIS
- # makehosts domain ...
- #
- # DESCRIPTION
- # This program works by using dnsfind() to recursively search
- # the desired domain(s) for all A, CNAME and PTR records.
- # The output is sorted by IP-number, and it is ensured that any
- # IP address will be translated to the name mentioned by its PTR
- # record, if more than one name corresponds to the same address.
- #
- # Note that the necessary PTR records must be provided by making
- # makehosts search in the appropriate "IN-ADDR.ARPA" subdomains.
- #
- # For example, if you want a hosts file for the domain
- # "deakin.edu.au", you need to specify that domain, plus the
- # reverse domains for any addresses corresponding to hosts in
- # "deakin.edu.au". You would need to say:
- #
- # makehosts \
- # deakin.edu.au \
- # 184.128.in-addr.arpa \
- # 132.139.in-addr.arpa
-
-
- push (@INC, '/src/config/util/perl');
-
- require 'dnsfind.pl';
-
- $Prog = substr ($0, rindex ($0, '/') + 1);
-
- $Version = '$Revision: 8.2 $';
- @F = split (/\s+/, $Version);
- $Version = $F[1];
- undef @F;
-
- #
- # Set the PATH, so we have a chance of finding "dig"
- #
- $ENV{'PATH'} = '/bin:/usr/bin:/usr/ucb:/usr/local/bin';
-
- &main (@ARGV);
-
- exit (0);
-
-
- ##############################################################################
- #
- sub main {
- local (@domains);
- local ($key, $value);
- local ($not_canonical);
- local (%done);
- local (@addr);
- local ($_);
-
- foreach (@_) {
- tr/A-Z/a-z/;
- push (@domains, $_);
- }
-
- #
- # Everybody needs localhost
- #
- $IN_A{'localhost.'} = '127.0.0.1';
-
- &dnsfind (@domains);
-
- #
- # A records
- #
- warn "- Checking A records\n";
-
- while (($key, $value) = each (%IN_A)) {
- undef %done;
- @addr = split (/:/, $value);
- foreach (@addr) {
- next if ($done{$_});
- $done{$_} = 1;
- $not_canonical = 1;
- #
- # Check for matching PTR record
- #
- if (length ($IN_PTR{$_})) {
- #
- # A boolean that says this name is not the canonical
- # name
- #
- $not_canonical =
- (&strcasecmp ($key,
- substr($IN_PTR{$_}, 0, length ($key)))
- != 0);
- } else {
- #
- # Explicit lookup
- #
- if (! &dig (join ('.', reverse (split (/\./, $_)),
- 'in-addr.arpa.'), "PTR")) {
- warn "WARNING - no PTR for \"$_\" ($key A)\n";
- }
- }
- push (@hosts, sprintf ("%03d.%03d.%03d.%03d %1d %s",
- split (/\./, $_), $not_canonical, $key));
- }
- }
-
- #
- # CNAME records
- #
- while (($key, $value) = each (%IN_CNAME)) {
- #
- # Check that there is an A record
- #
- if (defined ($IN_A{$value})) {
- @addr = split (/:/, $IN_A{$value});
- } else {
- #
- # Explicit lookup
- #
- @addr = &dig ($value, 'A');
- if (! @addr) {
- warn "WARNING - no A record \"$value\" ($key CNAME)\n";
- next;
- }
- }
- undef %done;
- foreach (@addr) {
- next if ($done{$_});
- $done{$_} = 1;
- push (@hosts, sprintf ("%03d.%03d.%03d.%03d 2 %s",
- split (/\./, $_), $key));
- }
- }
-
- #
- # PTR records
- #
- while (($key, $value) = each (%IN_PTR)) {
- @h = split (/:/, $value);
- foreach (@h) {
- if (! defined ($IN_A{$_})) {
- #
- # Explicit lookup
- #
- if (! &dig ($_, "A")) {
- warn "WARNING - no A record \"$_\" ($key PTR)\n";
- }
- }
- }
- }
-
- #
- # Sort @hosts
- #
- @hosts = sort (@hosts);
-
- #
- # Output hosts
- #
- $date_time = `date`; chop ($date_time);
- print (
- '# hosts - host-name/IP-address data base
- #
- # $Source: /proj/src/isc/cvs-1/bind/contrib/misc/dnsfind.shar,v $
- #
- # This file generated by ' . "\"$Prog\" $Version, on $date_time" . '
- # Domains searched:
- # ' . join ("\n#\t", @domains) . '
- #
- ');
-
- foreach (@hosts) {
- ($address, $dummy, $name) = split;
- $address = sprintf ("%d.%d.%d.%d", split (/\./, $address));
-
- #
- # Trim the trailing dot
- #
- $name =~ s/\.$//;
-
- #
- # Due to the edu.au, zone being officially known as EDU.AU, all
- # data for all domains under this zone is returned with EDU.AU,
- # in all uppercase, by DNS. We don't like this in /etc/hosts,
- # so we will endeavour to fold to lowercase here.
- #
- $name =~ s/EDU.AU$/edu.au/i;
-
- $short = $name;
- $short =~ s/\..*$//;
-
- print ($address, "\t");
- if (length ($address) < 8) {
- print ("\t");
- }
- print ($name, "\t");
- if (length ($name) < 24) {
- print ("\t");
- }
- print ($short, "\n");
- }
- return 0;
- }
-
-
- ##############################################################################
- #
- sub dnswanted {
- if ($Parent ne $parent_zone) {
- warn "- Searching $parent_zone, from $server\n";
- $Parent = $parent_zone;
- }
-
- if ($type eq 'A') {
- $IN_A{$zone} .= $value . ':';
- } elsif ($type eq 'CNAME') {
- $IN_CNAME{$zone} = $value;
- } elsif ($type eq 'PTR') {
- $address = $zone;
- $address =~ s/\.in-addr\.arpa\.?$//i;
- $address = join ('.', reverse (split (/\./, $address)));
- $IN_PTR{$address} .= $value . ':';
- }
- }
-